package icu.twtool.entity

import java.io.PrintStream
import java.nio.file.Path
import kotlin.io.path.readLines

/**
 * 习题
 */
class Exercise {

    /**
     * 算式集合
     */
    private val equations = mutableListOf<BinaryEquation>()

    /**
     * 当前习题算式数
     */
    val size: Int get() = equations.size

    fun get(index: Int): BinaryEquation {
        return equations[index]
    }

    /**
     * 向习题里添加算式
     */
    fun add(equation: BinaryEquation): Boolean {
        return !equations.contains(equation) && equations.add(equation)
    }

    /**
    * 输出习题
    *
    * @param column 习题每行的算式数
    * @param out 输出字符流，默认输出到控制台
    */
    fun write(column: Int = 5, answer: Boolean = true, out: PrintStream = System.out) {
        val len = equations.size.toString().length
        equations.forEachIndexed { index, equation ->
            if (index % column == 0) {
                if (index > 0) out.println()
                out.print("%${len}d ~ %${len}d :  ".format(index + 1, index + 5))
            }
            out.print(equation.toString(answer))
            out.print("    ")
        }
        out.println()
    }

    companion object {

        /**
         * 习题保存格式的行正则表达式
         */
        private val EXERCISE_LINE_REGEX = Regex("^\\s*\\d+\\s*~\\s*\\d+\\s*:(\\s*\\d+\\s*[+-]\\s*\\d+\\s*=\\s*\\d*\\s*)+$")

        /**
         * 读取习题文件
         *
         * @param path 习题文件的路径
         * @param len 读取习题算式数字的长度
         */
        @Throws(IllegalStateException::class)
        fun readFile(path: Path, len: Int = 3): Exercise {
            val result = Exercise()
            path.readLines().forEach {
                if (!it.matches(EXERCISE_LINE_REGEX)) error("文件格式错误")
                BinaryEquation.REGEX.findAll(it).forEach { match ->
                    val first = match.groupValues[1].toInt()
                    val second = match.groupValues[3].toInt()
                    result.add(
                        if (match.groupValues[2] == "+") AdditionBinaryEquation(first, second, len)
                        else SubtractionBinaryEquation(first, second, len)
                    )
                }
            }
            return result
        }
    }
}